import { _decorator, Color, Component, find, Graphics, Node, UITransform, Vec2, Vec3, Label, instantiate, sys, Tween, UIOpacity, tween, Prefab, Widget, game, Game, } from 'cc';
import { Unit } from '../Entity/Unit';
import GameEventMgr, { GameEvent } from '../Model/GameEventMgr';
import { GameStickerMgr, GameStickerType } from '../Model/GameStickerMgr';
import { Global, GuideTipData, UnitType } from '../Util/Global';
import AssetsMgr from '../Model/AssetsMgr';
import { EconomicViewUI } from '../UI/Component/EconomicViewUI';
import { FactoryViewUI } from '../UI/Component/FactoryViewUI';
import Dialog from '../UI/Dialog/Dialog';
import PoolManager from './PoolManager';
import { SkillViewUI } from '../UI/Component/SkillViewUI';
import { GuideTip } from '../Entity/UI/GuideTip';

const { ccclass, property } = _decorator;

export enum Drawlayer {
    Game,
    View,
    UI//绘制出来的线和视角保持一致大小
}

@ccclass('UICtrl')
export class UICtrl extends Component {
    @property(Graphics)
    gameGraphics: Graphics = null;
    @property(Graphics)
    viewGraphics: Graphics = null;
    @property(Graphics)
    uiGraphics: Graphics = null;
    @property(GameStickerMgr)
    GameStickerMgr: GameStickerMgr = null;

    @property(Node)
    dialogLayer: Node = null;

    @property(Node)
    mapInfoNode: Node = null;
    @property(Node)
    logInfoNode: Node = null;
    @property(Node)
    tipInfoNode: Node = null;
    @property(Label)
    gameTimeLabel: Label = null;

    @property(EconomicViewUI)
    economicViewUI: EconomicViewUI = null;
    @property(FactoryViewUI)
    factoryViewUI: FactoryViewUI = null;
    @property(SkillViewUI)
    skillViewUI: SkillViewUI = null;
    private static _instance: UICtrl = null;
    static get Instance() {
        if (UICtrl._instance == null) {
            let node = find("ViewCanvas");
            UICtrl._instance = node.getComponent(UICtrl);
            if (UICtrl._instance == null) {
                console.error("怎么没有UICtrl！");
            }
            UICtrl.UILayer = find('UICanvas').layer;
        }

        return UICtrl._instance;
    }

    static UILayer: number = 0;

    gameGraphicsTran: UITransform = null;
    viewGraphicsTran: UITransform = null;
    uiGraphicsTran: UITransform = null;

    protected start(): void {
        this.gameGraphicsTran = this.gameGraphics.getComponent(UITransform);
        this.viewGraphicsTran = this.viewGraphics.getComponent(UITransform);
        this.uiGraphicsTran = this.uiGraphics.getComponent(UITransform);

        GameEventMgr.Register(this, GameEvent.LogGameMessage, this.LogGameMessageHandler.bind(this));
        GameEventMgr.Register(this, GameEvent.TipGameMessage, this.TipGameMessageHandler.bind(this));

        GameEventMgr.Register(this, GameEvent.OnDrawLineByUICtrl, UICtrl.LineRenderer.bind(UICtrl));
        GameEventMgr.Register(this, GameEvent.OnDrawCircleByUICtrl, UICtrl.CircleRenderer.bind(UICtrl));

        // game.on(Game.EVENT_SHOW, this.onAppShow, this);
    }

    // protected onAppShow(){
    //     console.log('返回游戏');
    //     let widget = this.getComponent(Widget);
    //     widget.left = 0;
    //     widget.right = 0;
    //     widget.top = 0;
    //     widget.bottom = 0;
    //     widget.updateAlignment();
    // }

    protected update(dt: number): void {
        this.viewGraphics.clear();
        this.uiGraphics.clear();
        if (Global.gameManager.pause) {
            return;
        }
        this.gameGraphics.clear();
    }

    private static getDrawGraphic(layer: Drawlayer) {
        let tran = null;
        let graphics = null;
        if (layer == Drawlayer.View) {
            tran = this.Instance.viewGraphicsTran;
            graphics = this.Instance.viewGraphics;
        }
        else if (layer == Drawlayer.UI) {
            tran = this.Instance.uiGraphicsTran;
            graphics = this.Instance.uiGraphics;
        }
        else if (layer == Drawlayer.Game) {
            tran = this.Instance.gameGraphicsTran;
            graphics = this.Instance.gameGraphics;
        }

        return [graphics, tran];
    }

    static LineRenderer(startPos: Vec3, endPos: Vec3, color: Color, layer: Drawlayer = Drawlayer.UI): void {
        let draw = this.getDrawGraphic(layer);
        let graphics: Graphics = draw[0];
        let tran: UITransform = draw[1];
        if (tran == null) {
            return;
        }
        startPos = tran.convertToNodeSpaceAR(startPos);
        endPos = tran.convertToNodeSpaceAR(endPos);
        // 设置直线的样式
        graphics.lineWidth = 2; // 线宽
        graphics.strokeColor = color; // 线条颜色，这里设置为红色
        // 绘制
        graphics.moveTo(startPos.x, startPos.y);
        graphics.lineTo(endPos.x, endPos.y);
        graphics.stroke();
    }

    static CircleRenderer(center: Vec3, radius: number, color: Color, layer: Drawlayer = Drawlayer.View) {
        let draw = this.getDrawGraphic(layer);
        let graphics: Graphics = draw[0];
        let tran: UITransform = draw[1];
        if (tran == null) {
            return;
        }
        center = tran.convertToNodeSpaceAR(center);
        //设置圆形样式
        graphics.lineWidth = 2;
        graphics.strokeColor = color;
        // 绘制圆形
        graphics.circle(center.x, center.y, radius);
        graphics.stroke();
    }


    /**
     * 绘制夹角扇形区域
     * @param v1 第一个向量
     * @param v2 第二个向量
     * @param radius 扇形半径
     */

    static FanShapeRenderer(center: Vec3, v1: Vec2, v2: Vec2, radius: number, color: Color, layer: Drawlayer = Drawlayer.View) {
        let draw = this.getDrawGraphic(layer);
        let graphics: Graphics = draw[0];
        let tran: UITransform = draw[1];
        if (tran == null) {
            return;
        }
        let radian = v1.angle(v2);
        // 计算向量夹角
        // const angle = radian * (180 / Math.PI);

        // 将夹角转换为弧度
        // const angleRad = angle * (Math.PI / 180);

        center = tran.convertToNodeSpaceAR(center);
        // 扇形的起始角度为v1指向的角度
        const startAngle = Math.atan2(v1.y, v1.x);
        const endAngle = startAngle + radian;

        let startX = center.x + radius * Math.cos(startAngle)
        let startY = center.y + radius * Math.sin(startAngle)

        // 设置绘制的颜色
        // graphics.fillColor = Color.GRAY;
        graphics.lineWidth = 2;
        graphics.strokeColor = color;

        // 绘制扇形路径
        graphics.moveTo(center.x, center.y); // 从圆心开始
        graphics.lineTo(startX, startY); // 起始点
        graphics.arc(center.x, center.y, radius, startAngle, endAngle, true); // 绘制圆弧
        graphics.lineTo(center.x, center.y); // 返回圆心
        graphics.close(); // 闭合路径

        // 填充扇形
        // graphics.fill();
        graphics.stroke();
    }

    static CreateStickerRenderer(target: Unit, type: GameStickerType, msg?: string): Node {
        // let player = Global.gameManager.playerCtrl.playerUnit
        if (!target || target.death) {
            return null;
        }
        return this.Instance.GameStickerMgr.AddSticker_toTarget(target, type, msg);
    }

    static ClearStickerRenderer(target: Unit, type: GameStickerType) {
        this.Instance.GameStickerMgr.RemoveSticker_toTarget(type, target);
    }

    /**刷新信息显示 */
    UpdateMapInfo() {

        let mapCtrl = Global.gameManager.mapCtrl;
        let info = [];

        if (sys.isBrowser || Global.gameManager.gameover) {
            info = [
                `总量：${Global.gameManager.currentUnitLive.size}`,
                `飞船：${Global.gameManager.get_all_unit_count(UnitType.UnitSpacecra)}`,
                `星球：${mapCtrl.unitCountInMap}`,
                `回收：${PoolManager.pool_all_num}`,
            ]
        }

        let infoIndex = 0;
        let ch = this.mapInfoNode.children;
        for (let i = 0; i < ch.length; i++) {//已存在的信息节点，直接修改信息
            if (i >= info.length) {
                this.mapInfoNode.destroyAllChildren();
                break;
            }
            let label = ch[i].getComponent(Label);
            if (label) {
                label.string = info[i];
                infoIndex = i + 1;
            }
        }

        for (infoIndex; infoIndex < info.length; infoIndex++) {//缺少的增加

            let node = new Node();
            UICtrl.ChangeLayerToUI(node);
            node.parent = this.mapInfoNode;
            let label = node.addComponent(Label);
            if (label) {
                label.fontSize = 20;
                label.string = info[infoIndex];
                node.getComponent(UITransform).anchorPoint = new Vec2(0, 0.5);
            }
        }
    }

    /**在游戏界面打印游戏事件信息 */
    LogGameMessageHandler(message: string) {
        if (!sys.isBrowser || message == null || message.length <= 0) {
            return;
        }

        let messageNode = this.RefreshGameMessageRoot(message, this.logInfoNode);
        UICtrl.ChangeLayerToUI(messageNode);

        this.scheduleOnce(() => {
            messageNode.active = false;
        }, 3);
    }

    /**打印左上角游戏提示信息 */
    TipGameMessageHandler(message: string, delay: number = 2.5) {
        let messageNode = this.RefreshGameMessageRoot(message, this.tipInfoNode);
        UICtrl.ChangeLayerToUI(messageNode);
        let opacity = messageNode.addComponent(UIOpacity);
        opacity.opacity = 0;

        this.scheduleOnce(() => {
            opacity.opacity = 255;
            tween(opacity).delay(delay).to(0.5, { opacity: 0 }).call(() => { messageNode.active = false; }).start();
        })
    }

    /**从信息根节点找到可用的label填充信息，没有就新建一个 */
    private RefreshGameMessageRoot(message: string, root: Node): Node {
        let ch = root.children;
        let hasPrint = false;
        let printNode = null;
        for (let i = 0; i < ch.length; i++) {
            if (ch[i].active == false) {
                printNode = ch[i];
                let label = printNode.getComponent(Label);
                if (label) {
                    label.string = message;
                    hasPrint = true;
                    printNode.active = true;
                    break;
                }
            }
        }

        if (!hasPrint) {
            printNode = new Node();
            printNode.parent = root;
            let label = printNode.addComponent(Label);
            if (label) {
                label.fontSize = 20;
                label.string = message;
                printNode.getComponent(UITransform).anchorPoint = new Vec2(0, 0.5);
                hasPrint = true;
            }
        }

        // if (hasPrint) {
        //     this.scheduleOnce(() => {
        //         printNode.active = false;
        //     }, 3);
        // }

        return printNode;
    }

    private static dialogShowing: Map<string, Dialog> = new Map();

    static showDialog<T extends Dialog>(cls: { prototype: T } | string): T {
        let name = "";
        if (typeof cls == "string") {
            name = cls;
        } else {
            let obj = Object.create(cls.prototype);
            name = Object.getPrototypeOf(obj)["__classname__"];
            obj = null;
        }

        let d = this.dialogShowing.get(name);
        if (d && d.node) {
            return <T>d;
        }

        let dialogP = AssetsMgr.dialogPrefabMap.get(name);

        if (dialogP) {
            let node = instantiate(dialogP);
            node.parent = this.Instance.dialogLayer;

            let dialog = node.getComponent(name);
            this.dialogShowing.set(name, <T>dialog);

            return <T>dialog;
        }
        else {

            console.error("没找到这个弹窗-->" + name);
        }

        return null;
    }

    static hideDialog<T extends Dialog>(cls: { prototype: T } | string): T {
        let name = "";
        if (typeof cls == "string") {
            name = cls;
        } else {
            let obj = Object.create(cls.prototype);
            name = Object.getPrototypeOf(obj)["__classname__"];
            obj = null;
        }
        let d = this.dialogShowing.get(name);
        if (d && d.node) {
            d.close();
            return <T>d;
        }
        return null;
    }

    static clearDialog() {
        this.dialogShowing.forEach(d => {
            d.close();
        })
    }

    /**创建一个引导说明的消息显示在画面上 */
    static CreateGuideMessageOnGameScene(data: GuideTipData): GuideTip {
        let p = AssetsMgr.prefabMap.get('GuideTip');
        let guideNode = instantiate(p);
        let guide = guideNode.getComponent(GuideTip);
        guide.data = data;
        if (data.GameLayer) {
            guideNode.parent = data.target;
        }
        else {
            guide.uiTran = this.Instance.viewGraphicsTran;
            guideNode.parent = this.Instance.viewGraphicsTran.node;
            // this.ChangeLayerToUI(guideNode);
        }

        return guide;
    }

    static ChangeLayerToUI(node: Node, layer: number = UICtrl.UILayer) {
        node.layer = layer;
        for (let i = 0; i < node.children.length; i++) {
            let child = node.children[i];
            this.ChangeLayerToUI(child, layer);
            child.layer = layer;
        }
    }
}


